﻿// -----------------------------------------------------------------------
// <copyright file="AmazonService.cs" company="EPAM Systems">
////Copyright (c) EPAM Systems, 2012. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace MBOP.DistributedServices
{
	#region Usings

	using System;
	using System.Linq;
	using System.Text;
	using System.Text.RegularExpressions;

	using MBOP.Configuration.ConfigElements;
	using MBOP.Core.Entities.Library;
	using MBOP.DistributedServices.AmazonAPI;
	using MBOP.DistributedServices.AmazonHeaders;
	using MBOP.Helpers.Parsers;

	#endregion

	/// <summary>
	/// Handles interactions with amazon service
	/// </summary>
	public class AmazonService
	{
		#region Constants

		/// <summary>
		/// Represents the search index for books.
		/// </summary>
		private const string SEARCH_INDEX_BOOKS = "Books";
		
		/// <summary>
		/// Represents the response group for images.
		/// </summary>
		private const string RESPONSE_GROUP_IMAGES = "Images";
		
		/// <summary>
		/// Represents the response group for item attributes.
		/// </summary>
		private const string RESPONSE_GROUP_ITEM_ATTRIBUTES = "ItemAttributes";

		/// <summary>
		/// Represents the response group for editorial review.
		/// </summary>
		private const string RESPONSE_GROUP_EDITORIAL_REVIEW = "EditorialReview";

		/// <summary>
		/// Represents the regular expression for isbn validation.
		/// </summary>
		private const string REG_EXP_VALID_ISBN = @"[0-9]{9}[0-9xX]{1}";

		/// <summary>
		/// Represents the regular expression for ean validation.
		/// </summary>
		private const string REG_EXP_VALID_EAN = "[0-9]{12}[0-9xX]{1}";

		#endregion

		#region Public Methods

		/// <summary>
		/// Gets book from distributed service.
		/// </summary>
		/// <param name="bookID">The book id.</param>
		/// <returns>Book from distributed service.</returns>
		public Book GetBook(string bookID)
		{
			Book book = null;

			if (this.IsCorrectBookID(bookID))
			{
				using (AWSECommerceServicePortTypeClient amazonClient = new AWSECommerceServicePortTypeClient())
				{
					ItemLookupRequest lookupRequest = new ItemLookupRequest();

					lookupRequest.SearchIndex = SEARCH_INDEX_BOOKS;
					lookupRequest.IdType = bookID.Length == 13 ? ItemLookupRequestIdType.EAN : ItemLookupRequestIdType.ISBN;
					lookupRequest.IdTypeSpecified = true;
					lookupRequest.ItemId = new string[] { bookID };
					lookupRequest.ResponseGroup = new string[]
						{
							RESPONSE_GROUP_ITEM_ATTRIBUTES, RESPONSE_GROUP_IMAGES,
							RESPONSE_GROUP_EDITORIAL_REVIEW
						};

					ItemLookup itemLookup = new ItemLookup();

					itemLookup.Request = new ItemLookupRequest[] { lookupRequest };
					itemLookup.AssociateTag = SEARCH_INDEX_BOOKS;
					itemLookup.AWSAccessKeyId = AppConfigurationSection.GetInstance().DistributedServices.AmazonService.AccessKeyID;

					ItemLookupResponse response = amazonClient.ItemLookup(itemLookup);

					if (response.Items[0].Item != null)
					{
						Items items = response.Items.FirstOrDefault();

						Item item = null;

						if (items != null)
						{
							item = items.Item.FirstOrDefault();
						}

						if (item != null)
						{
							book = this.CreateBookFromAmazonData(item);
						}
					}
				}
			}

			return book;
		}

		#endregion

		#region Private Methods

		/// <summary>
		/// Creates book from amazon data.
		/// </summary>
		/// <param name="bookData">The book data.</param>
		/// <returns>The created book.</returns>
		private Book CreateBookFromAmazonData(Item bookData)
		{
			Book book = new Book();

			book.Title = bookData.ItemAttributes.Title;

			if (bookData.LargeImage != null)
			{
				book.Image = new MBOP.Core.Entities.Common.Image();
				book.Image.Uri = bookData.LargeImage.URL;
			}

			if (bookData.ItemAttributes.Author != null)
			{
				book.Authors = this.GetAuthorsStringFromArray(bookData.ItemAttributes.Author);
			}

			if (bookData.EditorialReviews != null)
			{
				EditorialReview description = bookData.EditorialReviews.FirstOrDefault();

				if (description != null)
				{
					book.Description = TextParser.ParseFromHtml(description.Content);
				}
			}

			book.ISBN = bookData.ItemAttributes.ISBN;
			book.EAN = bookData.ItemAttributes.EAN;

			return book;
		}

		/// <summary>
		/// Checks book id for valid isbn or ean number.
		/// </summary>
		/// <param name="bookID">The book id</param>
		/// <returns>The result of validation.</returns>
		private bool IsCorrectBookID(string bookID)
		{
			Regex isbnRegEx = new Regex(REG_EXP_VALID_ISBN);
			Regex eanRegEx = new Regex(REG_EXP_VALID_EAN);

			return !string.IsNullOrEmpty(bookID) && (isbnRegEx.IsMatch(bookID) || eanRegEx.IsMatch(bookID));
		}

		/// <summary>
		/// Gets authors string representation from array.
		/// </summary>
		/// <param name="authorsArray">The authors array.</param>
		/// <returns>Authors string representation.</returns>
		private string GetAuthorsStringFromArray(string[] authorsArray)
		{
			StringBuilder builder = new StringBuilder();

			for (int index = 0; index < authorsArray.Length; index++)
			{
				builder.Append(authorsArray[index]);

				if (index != authorsArray.Length - 1)
				{
					builder.Append(", ");
				}
			}

			return builder.ToString();
		}

		#endregion
	}
}